Micron Document
Gopher Proxy


gopher.conman.org:70 gopher.conman.org:70/0Gopher:Ext:mod_blog/html.c
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/************************************************************************
*
* Copyright 2020 by Sean Conner. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Comments, questions and criticisms can be sent to: sean@conman.org
*
*************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
#include <limits.h>

#include <lua.h>
#include <lauxlib.h>

#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 503
# error You need to compile against Lua 5.3 or higher
#endif

/**************************************************************************/

enum
{
UPV_ENTITY = 1,
UPV_UTF8 = 2,
};

struct _yycontext;

static int readchars (struct _yycontext *,char *,size_t);
static void tagi (struct _yycontext *,char const *);
static void tagb (struct _yycontext *,char const *);
static void endtag (struct _yycontext *);
static void setfield (struct _yycontext *,char const *);
static void deentifyn (struct _yycontext *,char const *,int);
static void deentify (struct _yycontext *,char const *);
static bool linecnt (struct _yycontext *);

#define YY_CTX_LOCAL
#define YY_PARSE(T) static T
#define YY_CTX_MEMBERS
size_t len;
char const *buffer;
int line;
int linepos;
lua_State *L;
luaL_Buffer buf;
bool pre;
#define YY_INPUT(yy,buf,result,max) result = readchars(yy,buf,max);

#include "html.i"

/**************************************************************************/

static int readchars(yycontext *yy,char *dest,size_t dlen)
{
size_t xfer;
if (dlen > INT_MAX)
dlen = INT_MAX;
xfer = dlen < yy->len ? dlen : yy->len;
memcpy(dest,yy->buffer,xfer);
yy->len -= xfer;
yy->buffer += xfer;
return (int)xfer;
}

/**************************************************************************/

static void tagi(yycontext *yy,char const *tag)
{
lua_createtable(yy->L,0,0);
lua_pushstring(yy->L,tag);
lua_setfield(yy->L,-2,"tag");
lua_pushboolean(yy->L,true);
lua_setfield(yy->L,-2,"inline");
lua_createtable(yy->L,0,0);
lua_setfield(yy->L,-2,"attributes");
}

/**************************************************************************/

static void tagb(yycontext *yy,char const *tag)
{
lua_createtable(yy->L,0,0);
lua_pushstring(yy->L,tag);
lua_setfield(yy->L,-2,"tag");
lua_pushboolean(yy->L,true);
lua_setfield(yy->L,-2,"block");
lua_createtable(yy->L,0,0);
lua_setfield(yy->L,-2,"attributes");
}

/**************************************************************************/

static void endtag(yycontext *yy)
{
lua_pushinteger(yy->L,luaL_len(yy->L,-2) + 1);
lua_insert(yy->L,-2);
lua_settable(yy->L,-3);
}

/**************************************************************************/

static void setfield(yycontext *yy,char const *name)
{
lua_pushstring(yy->L,name);
lua_insert(yy->L,-2);
lua_getfield(yy->L,-3,"attributes");
lua_insert(yy->L,-3);
lua_settable(yy->L,-3);
lua_pop(yy->L,1);
}

/**************************************************************************/

static void deentifyn(yycontext *yy,char const *num,int base)
{
lua_Integer v = strtoul(num,NULL,base);
lua_getfield(yy->L,lua_upvalueindex(UPV_UTF8),"char");
lua_pushinteger(yy->L,v);
lua_call(yy->L,1,1);
luaL_addvalue(&yy->buf);
}

/**************************************************************************/

static void deentify(yycontext *yy,char const *label)
{
lua_getfield(yy->L,lua_upvalueindex(UPV_ENTITY),label);
luaL_addvalue(&yy->buf);
}

/**************************************************************************/

static bool linecnt(yycontext *yy)
{
if (yy->__pos > yy->linepos)
{
yy->line++;
yy->linepos = yy->__pos;
}
return true;
}

/**************************************************************************/

static int parse(lua_State *L)
{
yycontext yyctx;
int rc;
lua_settop(L,1);
lua_createtable(L,0,0);
memset(&yyctx,0,sizeof(yyctx));
yyctx.buffer = luaL_checklstring(L,1,&yyctx.len);
yyctx.L = L;
yyctx.line = 1;
rc = yyparse(&yyctx);
yyrelease(&yyctx);
if (rc == 0)
lua_pushnil(L);
lua_pushinteger(L,yyctx.line);
lua_pushinteger(L,yyctx.linepos + 1);
return 3;
}

/**************************************************************************/

int luaopen_org_conman_app_mod_blog_html(lua_State *L)
{
lua_getglobal(L,"require");
lua_pushliteral(L,"org.conman.const.entity");
lua_call(L,1,1);
lua_getglobal(L,"require");
lua_pushliteral(L,"utf8");
lua_call(L,1,1);
lua_pushcclosure(L,parse,2);
return 1;
}
.

you're on gopher.conman.org^70/0Gopher:Ext:mod_blog/html.c
back link is gopher.conman.org:70/1Gopher:Ext:mod_blog/